// OGoMojo
// Whitemice.MOGI.RPC2.Task
// License: LGPL
// Copyright: Whitemice Consulting, 2006
// Author(s): Adam Tauno Williams (awilliam@whitemice.org)
using System;
using System.Globalization;
using Whitemice.MOGI;
using CookComputing.XmlRpc;

namespace Whitemice.MOGI.RPC2 {
	/// \brief Implementation of ITask
	public class Task : Whitemice.MOGI.RPC2.Document, ITask {
		/// \brief Constructor
		/// \param document An XmlRpcStruct document
		/// \param server Reference to server object	
		public Task(XmlRpcStruct document, Server server)
		 : base(document, server) {
			if (document.Contains("kilometers"))
				document["kilometers"] = Convert.ToString((int)document["kilometers"]);		 
		}
		
		/// \brief Provides the objects unique name
		public override string Name {
			get {
				if (document.Contains("id"))
				{
					string id = (string)this.document["id"];
					return ("Document/Task/" + id.Substring(id.LastIndexOf('/') + 1));
				} else
					return "Document/Task/0";
			}
		}
		
		/// \brief Accessor for the endDate value
		public DateTime EndDate {
			get {
				string endDate = document["endDate"].ToString();
				endDate = endDate.Substring(0, endDate.IndexOf(' '));
		  		return DateTime.ParseExact(endDate, "M/d/yyyy", new DateTimeFormatInfo());			
			}
			set {
				this.document["endDate"] = value;
			}
		}
		
		/// \brief Accessor for the startDate value
		public DateTime StartDate {
			get {
				string startDate = document["startDate"].ToString();
		  		startDate = startDate.Substring(0, startDate.IndexOf(' '));
		  		return DateTime.ParseExact(startDate, "M/d/yyyy", new DateTimeFormatInfo());
			}
			set {
				this.document["startDate"] = value;
			}
		}
		
		/// \brief Accessor for the Id of the executor
		/// \todo How to handle this needs some thought,  we want to be
		/// abstract this so that GroupDAV can use the same interface.
		public string Executor 
		{
			get 
			{
				string id;
				IDocument	executant;
				
				if (document.Contains("executor"))
				{
					id = ((string)((XmlRpcStruct)document["executor"])["id"]);
					id  = id.Substring(id.LastIndexOf('/') + 1);
					Console.WriteLine("Name={0} Id={1}", Name, id);
					if((bool)document["isTeamJob"] == true)
						Console.WriteLine("Name={0} Team Job", Name);
					executant = (IDocument)server.Get("Document/Contact/" + id);
					if (executant == null)
					{
						Console.WriteLine("Name={0} Executant is not a person, checking for team", Name);
						executant = (IDocument)server.Get("Document/Team/" + id);
					} else Console.WriteLine("Executant is a person");
					/*if((bool)document["isTeamJob"] == true)
						return "Document/Team/" + id;			
					return "Document/Account/" + id;*/
					if (!(executant == null))
						return executant.Name;
					Console.WriteLine("Name={0} Executant unresolvable", Name);
				} else Console.WriteLine("Name={0}: Task does not contain executor", Name);
				return null;
			}
			set
			{
				Document executant;
				
				switch(MOGI.DetermineType(value))
				{
					case DocumentType.Account:
						executant = (Account)server.Get(value);
						if (!(document.Contains("executor")))
							document.Add("executor", new XmlRpcStruct());
						document["executor"] = executant.document;
						break;
					case DocumentType.Team:
						break;
				}
			}
		}
		
		/// \brief Return the object name of the projects creator
		public string Creator 
		{
			get 
			{
				string id;
				
				if (document.Contains("creator"))
				{
					id = ((string)((XmlRpcStruct)document["creator"])["id"]);
					return "Document/Account/" + id.Substring(id.LastIndexOf('/') + 1);
				} else
					return null;
			}
			set
			{
				Account account;
				account = (Account)server.Get(value);
				if (!(document.Contains("creator")))
					document.Add("creator", new XmlRpcStruct());
				document["creator"] = account.document;			
			}
		}
		
		/// \brief Return the status of the task
		/// \note This method supports all known task status codes, but it is
		/// not neccesarily so that OGo actually uses all these codes; for
		/// instance the meaning of 15_divided and 27_reactivated are unknown.
		/// And is there a difference between 10_archived and 30_archived?
		public ETaskStatus Status 
		{
			get { return RPC2.TaskStatusFromRPCString(document["status"].ToString()); }
		 	set	{ document["status"] = RPC2.RPCStringFromTaskStatus(value); }
		}
		
		/// \brief Accessor for the keywords value
		public string Keywords 
		{
			get 
			{
				if (document.Contains("keywords"))
					return document["keywords"].ToString();
					else return "";
			}
			set 
			{			if (document.Contains("kilometers"))
				document["kilometers"] = Convert.ToString((int)document["kilometers"]);
				if (document.Contains("keywords"))
					document["keywords"] = value;
					else document.Add("keywords", value);
			} 
		}

		/// \brief Accessor for the name value
		public string Description { 
			get {
				return document["name"].ToString();
			}
			set {
				this.document["name"] = value;
			} 
		}
		
		/// \brief Accessor for the priority value
		/// \note VeryHigh = 1, High = 2, Average = 3, Low = 4, VeryLow = 5		
		public ETaskPriority Priority 
		{
			get 
			{
				switch ((int)document["priority"])
				{
					case 1: return ETaskPriority.VeryHigh;
					case 2: return ETaskPriority.High;
					case 4: return ETaskPriority.Low;
					case 5: return ETaskPriority.VeryLow;
					default: return ETaskPriority.Average;
				}
			} 
			set {
				this.document["priority"] = (int)value;
			}
		}
		
		/// \brief Accessor for the percentComplete value
		public int PercentComplete 
		{
			get 
			{
				if (document.Contains("percentComplete"))
					return (int)document["percentComplete"];
					else return 0;
			}
			set {
				if ((value > -1) && (value < 101))
					if (document.Contains("percentComplete"))
						document["percentComplete"] = value;
						else document.Add("percentComplete", value);
			}
		 }
		
		// \todo Implement, probably requires server patch
		public DateTime CompletionDate {
			get { return DateTime.Now; }
			set { }
		 }
		 
		/// \brief Accessor for the accountingInfo value
		public string Info 
		{
			get 
			{
				if (document.Contains("accountingInfo"))
					return (string)this.document["accountingInfo"];
					else return "";
			}
			set 
			{
				if (document.Contains("accountingInfo"))
					document["accountingInfo"]  = value.Trim();
					else document.Add("accountingInfo", value.Trim());
			}
		}
		
		/// \brief Accessor for the associatedCompanies value
		public string Companies 
		{
			get 
			{
				if (document.Contains("associatedCompanies"))
					return (string)document["associatedCompanies"];
					else return "";
			}
			set 
			{
				if (document.Contains("associatedCompanies"))
					document["associatedCompanies"] = value.Trim();
					else document.Add("associatedCompanies", value.Trim());
			}
		}
		
		/// \brief Accessor for the associatedContacts value
		public string Contacts 
		{
			get 
			{
				if (document.Contains("associatedContants"))
					return (string)document["associatedContacts"];
					else return "";
			}
			set 
			{
				if (document.Contains("associatedContacts"))
					document["associatedContacts"] = value.Trim();
					else document.Add("associatedContacts", value.Trim());
			}
		}
		
		/// \brief Accessor for the actualWork value
		public int ActualWork 
		{
			get 
			{
				if (document.Contains("actualWork"))
					return (int)this.document["actualWork"];
					else return 0;
			}
			set 
			{
				if (document.Contains("actualWork"))
					document["actualWork"] = value;
					else document.Add("actualWork", value);
			}
		}
		
		/// \brief Accessor for the totalWork value
		public int TotalWork 
		{
			get 
			{
				if (document.Contains("totalWork"))
					return (int)document["totalWork"];
					else return 0;
			}
			set 
			{
				if (document.Contains("totalWork"))
					document["totalWork"] = value;
					else document.Add("totalWork", value);
			}
		}
		
		/// \brief Accessor for the kilometers value
		public int Kilometers 
		{
			get 
			{
				if (document.Contains("kilometers"))	
					return Convert.ToInt32((string)document["kilometers"]);
					else return 0;
			}
			set 
			{
				if (document.Contains("kilometers"))
					document["kilometers"] = Convert.ToString(value);
					else document.Add("kilometers", Convert.ToString(value));
			}
		}
		
		/// \brief Accessor for the kilometers value converted into miles
		public int Miles 
		{
			get  { return Convert.ToInt32(Convert.ToDouble(Kilometers) * 0.6); }
			set  { Kilometers = Convert.ToInt32(Convert.ToDouble(value) * 1.2); }
		}
		
		/// \brief Accessor for the sensitivity value
		public ETaskSensitivity Sensitivity 
		{
			get 
			{
				if (document.Contains("sensitivity"))
					switch ((int)document["sensitivity"])
					{
						case 0 : return ETaskSensitivity.Public;
						case 1 : return ETaskSensitivity.Personal;
						case 2 : return ETaskSensitivity.Private;
						case 3 : return ETaskSensitivity.Confidential;
						default: return ETaskSensitivity.Undefined;
					}
					else return ETaskSensitivity.Undefined;
			}
			set 
			{
				if (document.Contains("sensitivity"))
					document["sensitivity"] = (int)value;
					else document.Add("sensitivity", (int)value);
			}
		}
		
		/// \brief Accessor for the category value
		public string Category { 
			get {
				return (string)this.document["category"];
			} 
			set {
				this.document["category"] = value.Trim();
			} 
		}		 
	}
}
